# ---------------------------------------------#
# iSpace Download Quiz Pages                             #
# Date:2024/06/07                             #
# Author:hejing                               #
# Email: hejing@uic.edu.cn
# update:2024/08/25                          #
# ---------------------------------------------#
import json
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import datetime
from bs4 import BeautifulSoup
from selenium.common.exceptions import StaleElementReferenceException


class iSpace:
    chrome_options = Options()
    chrome_options.add_argument('--enable-print-browser')
    # chrome_options.add_argument('--headless') #headless模式下，浏览器窗口不可见，可提高效率
    settings = {
        "recentDestinations": [{
            "id": "Save as PDF",
            "origin": "local",
            "account": ""
        }],
        "selectedDestinationId": "Save as PDF",
        "version": 2,
        "isHeaderFooterEnabled": False,

        # "customMargins": {},
        # "marginsType": 2,#边距（2是最小值、0是默认）
        # "scaling": 100,
        # "scalingType": 3,
        # "scalingTypePdf": 3,
        # "isLandscapeEnabled": True,  # 若不设置该参数，默认值为纵向
        "isCssBackgroundEnabled": True,
        "mediaSize": {
            "height_microns": 297000,
            "name": "ISO_A4",
            "width_microns": 210000,
            "custom_display_name": "A4"
        },
    }
    prefs = {
        'printing.print_preview_sticky_settings.appState': json.dumps(settings),
        # 此处填写你希望文件保存的路径,可填写your file path默认下载地址
        # 'savefile.default_directory': 'D://UIC//iSpace-Grouping//lab-quiz-download//quiz'
    }
    chrome_options.add_argument('--kiosk-printing')  # 静默打印，无需用户点击打印页面的确定按钮
    chrome_options.add_experimental_option('prefs', prefs)

    driver = webdriver.Chrome(options=chrome_options)
    # driver = webdriver.Chrome()
    url = "https://ispace.uic.edu.cn/login/index.php"
    username = ''
    password = ''
    group_name = []

    def __init__(self, username, password, courseid):
        # self.url = url
        self.username = username
        self.password = password
        self.courseid = courseid
        self.group_name = []
        self.user_group_data = dict()

    def login_system(self):
        """
        User should login first.
            1. Open login page.
            2. Input username and password.
            3. Click login button.
            4. Open new tab for later use.
            5. Switch to first tab.
            6. Get cookies.

        :return: None.
        """
        try:
            self.driver.get(self.url)
            # 睡眠2秒
            time.sleep(1)

            # input username and password
            self.driver.find_element(
                By.ID, "username").send_keys(self.username)

            self.driver.find_element(
                By.ID, "password").send_keys(self.password)

            # click login button
            self.driver.find_element(By.ID, "loginbtn").click()

            time.sleep(2)
            # open new tab for later use
            self.driver.execute_script("window.open('');")

            # switch to first tab
            self.driver.switch_to.window(self.driver.window_handles[0])

            # drive.switch_to_default_content()
            # cookies_list = self.driver.get_cookies()
            # print(cookies_list)

        except Exception as e:
            print("出现问题", e)

    def get_group_data(self, filename):
        """
        Get group data from txt.
            1. Read txt file.  Format: student_email, group_name
            2. Create a dictionary.
            3. Return the dictionary.

        :param filename: txt file name.
        """
        with open(filename, "r", encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                data = line.strip("\n").split(",")

                if data[1] in self.user_group_data.keys():
                    self.user_group_data[data[1]].append(data[0])
                else:
                    self.user_group_data[data[1]] = [data[0]]

        # put group names into list
        self.group_name.extend(self.user_group_data.keys())

        print(self.user_group_data)
        print(self.group_name)

        self.create_groups()
        self.add_user_into_group()

    def create_groups(self):
        """
        Create groups.
            1. Open grouping page.
            2. Input group name.
            3. Click create group button.
            4. Repeat step 2 and 3 for all groups.
        """

        for item in self.group_name:
            group_url = f"https://ispace.uic.edu.cn/group/group.php?courseid={self.courseid}"
            # print(group_url)

            # open grouping page
            self.driver.get(group_url)
            time.sleep(2)

            # input group name
            self.driver.find_element(By.ID, "id_name").send_keys(item)
            # click create group button
            self.driver.find_element(By.ID, "id_submitbutton").click()

    def add_user_into_group(self):
        """
        Put users into groups.
            1. Open group page.
            2. Select group.
            3. Click add members button.
            4. Input user name.
            5. Click add button.
            6. Repeat step 4 and 5 for all users.
            7. Click save button.

        """

        for _ in range(len(self.user_group_data)):

            group_url = f"https://ispace.uic.edu.cn/group/index.php?id={self.courseid}"
            self.driver.get(group_url)
            time.sleep(2)

            # select group
            groups = self.driver.find_element(By.ID, "groups")
            # get options
            options = groups.find_elements(By.TAG_NAME, "option")

            for option in options:
                print(option.text)

                # looping each item group
                # for option in options:
                if "(0)" not in option.text:
                    continue
                option_text = option.text.replace(" (0)", "")

                # 点击每一个分组
                option.click()
                self.driver.find_element(By.ID, "showaddmembersform").click()
                time.sleep(1)

                # get the name list in current group
                name_list = self.user_group_data[option_text]

                for name in name_list:
                    self.driver.find_element(
                        By.ID, "addselect_searchtext").send_keys(name)
                    time.sleep(1)
                    target = self.driver.find_element(
                        By.ID, "addselect").find_elements(By.TAG_NAME, "option")[0]
                    target.click()
                    time.sleep(1)
                    self.driver.find_element(
                        By.CSS_SELECTOR, "#add").send_keys(Keys.ENTER)
                    time.sleep(1)
                    self.driver.find_element(
                        By.ID, "addselect_clearbutton").click()
                    time.sleep(1)

                # 页面更新，options变化, 找不到元素索引，会报 StaleElementReferenceException
                # 需要跳出循环，重新获取 options
                break

        print("添加用户成功")

    def get_quiz_links(self, quizid):
        """
        Download quiz page.
            1. Open quiz page.
            2. Set page size to 1000.
            3. Click attempt counts button.
            4. Get all quiz links.
            5. Download each quiz page.
            6. Get student info.
            7. Print page.
            8. Repeat step 1 to 7 for all quizzes.
            9. Close all tabs.

        :param quizid: quiz id.
        """
        # quiz_url = f"https://ispace.uic.edu.cn/mod/quiz/report.php?id={quizid}"

        # open quiz page
        quiz_url = f"https://ispace.uic.edu.cn/mod/quiz/view.php?id={quizid}"
        # set page size to 1000
        self.driver.get(quiz_url)
        time.sleep(2)

        # quiz attempt page
        self.driver.find_element(By.CLASS_NAME, "quizattemptcounts").click()
        time.sleep(2)

        # reset page size to 1000
        self.driver.find_element(By.ID, "id_pagesize").clear()
        self.driver.find_element(By.ID, "id_pagesize").send_keys(1000)
        self.driver.find_element(By.ID, "id_onlygraded").click()
        self.driver.find_element(By.ID, "id_submitbutton").click()
        time.sleep(4)

        # get all quiz links
        html_text = self.driver.page_source
        soup = BeautifulSoup(html_text, 'html.parser')
        reviewlinks = soup.find_all(class_="reviewlink")
        print(len(reviewlinks))

        # download each quiz page
        self.download_page(reviewlinks)

    def download_page(self, reviewlinks):
        """
        Download page.
            1. Open each quiz page.
            2. Set page size to 1000.
            3. Click attempt counts button.
            4. Get all quiz links.
            5. Download each quiz page.
            6. Get student info.
            7. Print page.
            8. Repeat step 1 to 7 for all quizzes.
            9. Close all tabs.
        """
        # looping each quiz link
        for idx, link in enumerate(reviewlinks):
            print(idx, link['href'])

            # open current quiz link
            self.driver.get(link['href'])
            time.sleep(3)
            # 获取用户信息页面
            student_info = self.get_student_info()

            # 切换回第一个tab
            self.driver.switch_to.window(self.driver.window_handles[0])

            # 打印页面资料
            time1 = datetime.datetime.now()
            time1 = time1.strftime('%Y-%m-%d-%H-%M')  # 只取年月日，时分秒

            # 删除 outcome / comment / history / info(state / grade)

            js = "document.querySelectorAll('.outcome').forEach(v=>v.remove())"
            self.driver.execute_script(js)
            js = "document.querySelectorAll('.comment').forEach(v=>v.remove())"
            self.driver.execute_script(js)
            js = "document.querySelectorAll('.history').forEach(v=>v.remove())"
            self.driver.execute_script(js)
            # js = "document.querySelectorAll('.state').forEach(v=>v.remove())"
            # self.driver.execute_script(js)
            # js = "document.querySelectorAll('.grade').forEach(v=>v.remove())"
            # self.driver.execute_script(js)
            js = "document.querySelectorAll('.info').forEach(v=>v.remove())"
            self.driver.execute_script(js)
            
            # put the student sid and name on the page 
            js = f"t =    document.querySelector('.quizreviewsummary'); newrow = t.insertRow(0);cell0 = newrow.insertCell(0);cell1 = newrow.insertCell(1); cell0.innerHTML='Student'; cell1.innerHTML='{student_info}';"
            self.driver.execute_script(js)

            self.driver.execute_script(
                f'document.title="{student_info}-{time1}.pdf";window.print();')

    def get_student_info(self, link=None):
        """
        Get student info.
            1. Open user info page.
            2. Get student name and sid.
            3. Return student info.

        :param link: user info page link.
        :return: student info.
        """
        time.sleep(3)
        # find student info link
        html_text = self.driver.page_source
        soup = BeautifulSoup(html_text, 'html.parser')
        # user_link = soup.find(class_="quizreviewsummary").find('a')['href']
        user_link = soup.find(id="user-picture").find('a')['href']
        print("user_link ---> ", user_link)
        self.driver.switch_to.window(self.driver.window_handles[1])
        self.driver.get(user_link)
        time.sleep(1)
        html_text = self.driver.page_source
        soup = BeautifulSoup(html_text, 'html.parser')
        name = soup.find(class_="userprofile").find(
            class_="page-header-headings").text
        name = name.split("(")[0].strip()
        # sid = soup.find_all(class_="contentnode")[3].find("dd").text
        sid = soup.find_all(class_="card-body")[1].find_all("dd")[-1].text
        sid = sid[:10]
        print(f"sid {sid} - name {name}")
        return f'{sid}-{name}'

    def enroll_student(self, student_email_file):
        """
        Enroll student.
            1. Open enroll page.
            2. Input student email.
            3. Click enroll button.
            4. Repeat step 2 and 3 for all students.

        :param student_email_file: student email file name.
        """
        # open enroll user page  e.g. https://ispace.uic.edu.cn/user/index.php?id=4517
        enroll_url = f"https://ispace.uic.edu.cn/user/index.php?id={self.courseid}"
        # set page size to 1000
        self.driver.get(enroll_url)

        # looping each email
        with open(student_email_file, "r", encoding='utf-8') as f:
            lines = f.readlines()
            for line in lines:
                useremail = line.strip("\n")

                # click enroll button
                self.driver.find_element(By.ID, "enrolusersbutton-1").click()
                time.sleep(2)

                # locate the input box
                # id_maincontainer
                div_block = self.driver.find_element(By.ID, "id_maincontainer")

                search_inputs = div_block.find_elements(By.TAG_NAME, "input")
                print("------------------------------------------")
                print(len(search_inputs))
                search_input = search_inputs[1]

                print("------------------------------------------")
                search_input.send_keys(useremail)

                time.sleep(3)
                # click the enroll user
                # form-autocomplete-suggestions

                self.driver.find_element(
                    By.CLASS_NAME, "form-autocomplete-suggestions").find_element(By.TAG_NAME, "li").click()
                time.sleep(3)

                # click the enroll button
                self.driver.find_element(
                    By.XPATH, "//button[text()='Enrol users']").click()

                time.sleep(5)

        pass


if __name__ == '__main__':

    # update to your course id
    COURSE_ID = 4053

    USERNAME = "hejing"
    # ispace password
    PASSWORD = input("iSpace Password:")
    # PASSWORD = ''

    # constructor
    ispace = iSpace(USERNAME, PASSWORD, COURSE_ID)
    # step 1
    ispace.login_system()
    
    # 导入学生到iSpace
    # file = '2024-cds-ai-pm.txt'
    # ispace.enroll_student(file)
    
    # 创建分组并将学生加入到对应小组 
    file = "courseid_4053_groups_data.txt"
    ispace.get_group_data(file)

    # quizid = 122516
    # ispace.get_quiz_links(quizid)
